/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						         transition_mask.h

	$Header: /resource_editor/transition_mask.h $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "transition_mask.h"

#include "streambuf_operators.h"

char const t_resource_traits<t_transition_set_array>::prefix[] = "transition";

char const t_resource_traits<t_transition_set_array>::extension[] = "psd";

// ------------------------------------------------------------------
// transition mask
// ------------------------------------------------------------------

int const t_transition_mask::k_offsets[2][k_adventure_tile_width] =
{
	// offsets for 1-bit transition masks
	{     0,   1,   2,   3,   4,   5,   6,   7,   8,  10,  12,  14,  16,  18,  20,  22,  24,
		 27,  30,  33,  36,  39,  42,  45,  48,  52,  56,  60,  64,  68,  72,  76,  80,  84,
		 88,  92,  96, 100, 104, 108, 112, 115, 118, 121, 124, 127, 130, 133, 136, 138, 140, 
		142, 144, 146, 148, 150, 152, 153, 154, 155, 156, 157, 158,	159
	},
	// offsets for 4-bit transition masks
	{     0,   1,   2,   4,   6,   9,  12,	16,	 20,  25,  30,  36,  42,  49,  56,  64,  72,
	     81,  90, 100, 110, 121, 132, 144, 156, 169, 182, 196, 210, 225, 240, 256, 272, 288,
		304, 319, 334, 348,	362, 375, 388, 400, 412, 423, 434, 444,	454, 463, 472, 480,	488,
		495, 502, 508, 514,	519, 524, 528, 532,	535, 538, 540, 542, 543
	}
};

// ------------------------------------------------------------------
// transition mask
// ------------------------------------------------------------------
int const t_transition_mask::k_column_start[k_adventure_tile_width] =
{
	15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10,  9,  9,  8,  8, 
	 7,  7,  6,  6,  5,  5,  4,  4,  3,  3,  2,  2,  1,  1,  0,  0,  
	 0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7, 
	 8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 
};

int const t_transition_mask::k_column_stop[k_adventure_tile_width] =
{
	16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23,
	24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31,
	31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24, 24,
	23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16, 16
};

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
t_transition_mask::t_transition_mask()
{
	m_data = 0;
	m_bits = 0;
	m_code = 0;
}

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
t_transition_mask::t_transition_mask( t_transition_mask const& arg )
{
	copy( arg );
}

t_transition_mask& t_transition_mask::operator=( t_transition_mask const& arg )
{
	if (m_data != 0)
		delete m_data;
	copy( arg );
	return *this;
}

void t_transition_mask::copy( t_transition_mask const& arg )
{
	m_bits = arg.m_bits;
	m_code = arg.m_code;
	m_data = 0;
	if (arg.m_data != 0)
	{
		int size = get_data_size();

		m_data = new t_uint8[size];
		memcpy( m_data, arg.m_data, size );
	}
}

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
t_transition_mask::~t_transition_mask()
{
	if (m_data != 0)
		delete m_data;
}

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
void t_transition_mask::create( int bits )
{
	int old_bits = m_bits;

	m_bits = bits;
	if (m_bits != old_bits)
	{
		if (m_data != 0)
			delete m_data;
		m_data = new t_uint8[get_data_size()];
	}
}

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
bool t_transition_mask::read( std::streambuf& buffer )
{
	t_uint8 old_bits = m_bits;
	int     size;

	buffer >> m_code >> m_bits;
	size = get_data_size();
	if (m_bits != old_bits)
	{
		if (m_data != 0)
			delete m_data;
		m_data = new t_uint8[size];
	}
	::read( buffer, m_data, size );
	return true;
}

// -------------------------------------------------------------------------------
// transition mask definition
// -------------------------------------------------------------------------------
bool t_transition_mask::write( std::streambuf& buffer ) const
{
	buffer << m_code << m_bits;
	if (m_data != 0)
		::write( buffer, m_data, get_data_size() );
	return true;
}


// ------------------------------------------------------------------
// read a transition set
// ------------------------------------------------------------------
bool t_transition_set::read( std::streambuf& buffer )
{
	if (!read_string16( buffer, m_name ))
		return false;

	int count;

	buffer >> count;
	if (count < 0 || count > 1000)
		return false;
	resize( count );

	iterator index;

	for (index = begin(); index != end(); index++)
		if (!index->read( buffer ))
			return false;
	return true;
}

// ------------------------------------------------------------------
// write a transition set
// ------------------------------------------------------------------
bool t_transition_set::write( std::streambuf& buffer) const
{
	if (!write_string16( buffer, m_name ))
		return false;

	buffer << size();

	const_iterator index;

	for (index = begin(); index != end(); index++)
		if (!index->write( buffer ))
			return false;
	return true;
}

// ------------------------------------------------------------------
// read a transition set array
// ------------------------------------------------------------------
bool read( std::streambuf& buffer, t_transition_set_array& array )
{
	int size = buffer.sbumpc();
	int i;

	array.resize( size );
	for (i = 0; i < size; i++)
		if (!array[i].read( buffer ))
			return false;
	return true;
}

// ------------------------------------------------------------------
// write a transition set array
// ------------------------------------------------------------------
bool write( std::streambuf& buffer, t_transition_set_array const& array )
{
	int i;

	buffer.sputc( array.size() );
	for (i = 0; i < array.size(); i++)
		if (!array[i].write( buffer ))
			return false;
	return true;
}
